package com.miracle9.game.server.message;

import com.miracle9.game.util.ClientIpProcess;
import com.miracle9.game.util.MyApplicationContext;
import com.miracle9.game.util.MyUtil;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

@Service("promoterAppSocketHandler")
public class PromoterAppSocketHandler
        implements IoHandler {

    private Logger logger = Logger.getLogger(PromoterAppSocketHandler.class);

    public void exceptionCaught(IoSession session, Throwable arg1)
            throws Exception {
        this.logger.error("", arg1);
        session.close(true);
    }

    public void messageReceived(IoSession session, Object message)
            throws Exception {
        try {
            IoBuffer in = (IoBuffer) message;
            int dataLength = in.getInt();
            byte[] contentBytes = new byte[dataLength];
            in.get(contentBytes);

            contentBytes = MyUtil.Base64Decode_session(contentBytes, session);

            Amf3Input ai = new Amf3Input(SerializationContext.getSerializationContext());
            ai.setInputStream(new ByteArrayInputStream(contentBytes));
            HashMap map = (HashMap) ai.readObject();

            //this.logger.info("推广员messageReceived："+ JSONObject.fromObject(map).toString());

            String url = (String) map.get("method");
            Object[] args = (Object[]) map.get("args");
            double time = ((Double) map.get("time")).doubleValue();

            String version = (String) map.get("version");
            if ((version == null) || (com.miracle9.game.util.GameParameterAssist.aE.compareTo(version) > 0)) {
                this.logger.info("disallow this client to send request,client version:" + version);
                session.close(true);
                return;
            }
            if (System.currentTimeMillis() - time >= 5000.0D) {
                this.logger.info("请求时间大于5秒");
                return;
            }
            String[] urls = url.split("/");
            String beanId = urls[0];
            String method = urls[1];
            String argsStr = method + "请求参数：";
            for (Object o : args) {
                argsStr = argsStr + o + ";";
            }
            if ("heart".equalsIgnoreCase(method)) {
                return;
            }
            if ((!com.miracle9.game.util.GameParameterAssist.bx.containsValue(session)) && (!"login_getEncrytKey".equals(method)) &&
                    (!"promoterLogin".equals(method)) && (!com.miracle9.game.util.GameParameterAssist.by.containsValue(session))) {
                this.logger.info("未登录操作");
                return;
            }
            Object[] args_login = new Object[args.length + 1];
            for (int i = 0; i < args.length; i++) {
                args_login[i] = args[i];
            }
            args_login[(args_login.length - 1)] = session;
            args = args_login;
            Object service = MyApplicationContext.a().getBean(beanId);
            Method m = service.getClass().getDeclaredMethod(method, getClasses(args));
            Object result = m.invoke(service, args);
            if (result != null) {
                AmfMessageSend.storageMethodOperating.notifyAllOperating(new StorageMethodEntity(session, method, new Object[]{result}));
            }
        } catch (Exception e) {
            this.logger.error("", e);
        }
    }

    private Class<?>[] getClasses(Object[] args) {
        try {
            Class[] classArray = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                classArray[i] = args[i].getClass();
                if ((args[i] instanceof Integer)) {
                    classArray[i] = Integer.TYPE;
                } else if ((args[i] instanceof Boolean)) {
                    classArray[i] = Boolean.TYPE;
                } else if ((args[i] instanceof Map)) {
                    classArray[i] = Map.class;
                } else if ((args[i] instanceof Long)) {
                    classArray[i] = Long.TYPE;
                } else if ((args[i] instanceof Double)) {
                    classArray[i] = Double.TYPE;
                } else if ((args[i] instanceof IoSession)) {
                    classArray[i] = IoSession.class;
                } else if ((args[i] instanceof Float)) {
                    classArray[i] = Float.TYPE;
                }
            }
            return classArray;
        } catch (Exception e) {
            this.logger.error("", e);
        }
        return null;
    }

    public void messageSent(IoSession arg0, Object arg1)
            throws Exception {
    }

    public void sessionClosed(IoSession session)
            throws Exception {
        this.logger.info("sessionClosed...");
        if (com.miracle9.game.util.GameParameterAssist.bd.containsKey(session)) {
            com.miracle9.game.util.GameParameterAssist.bd.remove(session);
        }
        if (com.miracle9.game.util.GameParameterAssist.bx.containsValue(session)) {
            Object id = session.removeAttribute("id");
            if (id != null) {
                com.miracle9.game.util.GameParameterAssist.bx.remove(Integer.valueOf(id.toString()));
            }
        }
        if (com.miracle9.game.util.GameParameterAssist.by.containsValue(session)) {
            Object id = session.removeAttribute("id");
            if (id != null) {
                com.miracle9.game.util.GameParameterAssist.by.remove(Integer.valueOf(id.toString()));
            }
        }
        if (com.miracle9.game.util.GameParameterAssist.bA.containsKey(session)) {
            com.miracle9.game.util.GameParameterAssist.bA.remove(session);
        }
    }

    public void sessionCreated(IoSession arg0)
            throws Exception {
    }

    public void sessionIdle(IoSession session, IdleStatus arg1)
            throws Exception {
        this.logger.info("exceptionCaught...");
        session.close(true);
    }

    public void sessionOpened(IoSession session)
            throws Exception {
        String clientIP = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
        session.setAttribute("ip", clientIP);
        this.logger.info("推广员打开了会话  sessionOpened, session:" + session);
        com.miracle9.game.util.GameParameterAssist.bA.put(session, Long.valueOf(System.currentTimeMillis()));
        ClientIpProcess.startMethod().clientIPSession(session);
    }

}
